using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
// Additional CF classes required.
using System.Collections;
using System.IO;
using Microsoft.WindowsMobile.Forms;
using Microsoft.WindowsMobile.PocketOutlook;

namespace TabbedWebBrowser
{

    // A C# application that creates a tabbed web browser.
    // Multiple WebBrowser controls are maintained by a Tab Control.

    /* 
    Copyright (c) Microsoft Corporation.  All rights reserved.
    Use of this sample source code is subject to the terms of the Microsoft license 
    agreement under which you licensed this sample source code and is provided AS-IS.
    If you did not accept the terms of the license agreement, you are not authorized 
    to use this sample source code.  For the terms of the license, please see the 
    license agreement between you and Microsoft.
    */

    public partial class BrowserForm : Form
    {
        // This windows form contains a tab control and
        // each tab has an associated WebBrowser control for displaying
        // web content. 
        // An extra tab is always present - selecting this empty tab opens
        // another new web browser page
        // (there is a menu option to do the same).

        // A constant to define the tab page that creates a new page.
        const string pagetypeNew = "new page";

        // A flag to temporarily stop handling the selected tab changed message
        bool handlerActive = true;

        // Static variables that can be accessed by the "NewURL" form.
        static public string newUrl;
        static public bool openInNewTab;

        // These lists store the WebBrowser and TabControls.
        List<TabPage> listOfTabpages = new List<TabPage>();
        List<WebBrowser> listOfWebpages = new List<WebBrowser>();


        public BrowserForm()
        {
            InitializeComponent();

            tabControl.Controls.Clear();	// Remove any existing tab pages.
            listOfTabpages.Clear();		// Remove any existing tabpages
            listOfWebpages.Clear();		// Remove any existing webpages
            CreateTheNewEmptyTab();     // Add the tag for opening new pages.
            CreateANewTab();             // This method creates a new tab, a new webbrowser and opens

            // Load up the default home page, which we create programmatically.
            WebBrowser thisWebPage = GetCurrentWebBrowser();
            CreateDocument();
            thisWebPage.Navigate(new Uri("file://\\browser_index.htm"));
        }


        // TabControl Related Methods

        private void CreateTheNewEmptyTab()
        {
            // Add a new tab control, that exists only as a "button"
            // to trigger the creation of a new tab and webbrowser pair.

            // This tab will always be the last tab in the tab control,
            // reading from left to right.

            // Create the new tab page
            TabPage newPage = new TabPage();
            newPage.Name = pagetypeNew;


            // Add the page to the TabControl so it appears on-screen.
            tabControl.TabPages.Add(newPage);

        }

        private void CreateANewTab()
        {
            // Add a new tab control, and put a web browser control in it.

            // You may want to place try/catch code around the 'new' statements
            // below in case the tab controls and/or webbrowser controls cannot
            // be instantiated due to lack of resources.


            TabPage newpage = new TabPage();                // Create the new tab page
            newpage.Text = "...";							// Display something in the tab as it loads.

            // Add the page before the last tab that currenly exists.
            tabControl.TabPages.Insert(tabControl.TabPages.Count - 1, newpage);
            listOfTabpages.Add(newpage);					// Keep track of open tabs in a list.

            // Create a new WebBrowser control.
            WebBrowser webpage = new WebBrowser();          // Create the new control
            webpage.Parent = this;	                        // Make sure the WebBrowser control's parent is the TabControl page
            webpage.Dock = DockStyle.Fill;
            listOfWebpages.Add(webpage);                  // Add the webpage we just created to a list, so we can keep track of it.

            // We define a handler to perform some actions when the document has been fetched and displayed.
            // We need to do this as the WebControl will work in the background, and we need to know when it has
            // finished so we can switch off the animation timer, and update the name of the Tab with the
            // the document title.

            webpage.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webpage_DocumentCompleted);

            // Select the new tab as the currently displayed tab, display it and its WebBrowser and hide all the other
            // WebBrowser controls currently open.

            // Make this tab the currently selected one.
            tabControl.SelectedIndex = listOfTabpages.Count - 1;
            webpage.Show();
        }

        private void UpdateName(TabPage current_tab)
        {	// Update the name of the current tab by looking
            // at the document it is displaying. 

            WebBrowser thiswebpage = GetWebBrowser(current_tab);

            if (thiswebpage.Url != null)
                if (thiswebpage.Url.Host.ToString().Length != 0)
                {
                    // This code could be refined to display a shorter and
                    // more meaningful name on the tab.
                    current_tab.Text = thiswebpage.Url.Host.ToString();

                }
                else
                {
                    // If null, then either a page has failed to load
                    // or we're displaying the default. You may want
                    // to refine this section of the code.
                    current_tab.Text = "Home";

                }

        }

        private void UpdateAllNames()
        {

            // Update all the tab names for all the currently open web pages.
            foreach (TabPage tp in listOfTabpages)
                UpdateName(tp);

            // Also update the Left Soft key (the Back option) 
            UpdateLeftSoftKey(listOfTabpages[tabControl.SelectedIndex]);

        }

        private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            // This method is called every time the currently selected 
            // tab changes. This happens when the user clicks on a new tab,
            // but also when a new tab is made active: perhaps when another
            // tab is deleted.

            // First, confirm that we need to handle this message.
            if (!handlerActive)
                return;

            if (tabControl.TabPages[tabControl.SelectedIndex].Name == pagetypeNew)
            {
                // The user has selected the "new" tab, so create a new tab and
                // web page, and load the default web page.
                CreateANewTab();
                WebBrowser thiswebpage = GetCurrentWebBrowser();
                thiswebpage.Navigate(new Uri("file://\\browser_index.htm"));
            }
            else
            {
                // The user has selected an existing tab, so bring the
                // associated WebBrowser to the foreground.
                HideAllWebBrowsers();
                ShowCurrentWebBrowser();
                UpdateLeftSoftKey(listOfTabpages[tabControl.SelectedIndex]);
            }
        }


        // WebBrowser Related Methods

        private void HideBrowser(WebBrowser wb)
        {
            // Hide the currently displayed WebBrowser.

            if (wb != null)
                wb.Hide();
        }

        private void HideAllWebBrowsers()
        {	// Hide all the WebBrowsers.

            foreach (TabPage tp in listOfTabpages)
            {
                HideBrowser(GetWebBrowser(tp));
            }

        }

        private void ShowCurrentWebBrowser()
        {	// Display the currently active WebBrowser.

            WebBrowser wb = GetCurrentWebBrowser();

            if (wb != null)
                wb.Show();
        }

        private WebBrowser GetCurrentWebBrowser()
        {
            // This method returns the currently active WebBrowser control. 
            return listOfWebpages[tabControl.SelectedIndex];
        }

        private WebBrowser GetWebBrowser(TabPage tp)
        {
            // Return the WebBrowser control for a given tab page.    
            return listOfWebpages[listOfTabpages.IndexOf(tp)];
        }

        void webpage_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {	// This method is called when a webpage has completed rendering.
            // It's called because we asked the WebBrowser control to send this message: once
            // the message is sent, we know the web page has been loaded and we can update the
            // tab with the name of the page.

            // Update the names of the tabs by looking at the HTML document title.
            UpdateAllNames();


        }

        private void CreateDocument()
        {	// Create an HTML document comprising presets and favorites,
            // and then save this local. We need to create an actual file,
            // rather than passing a long string of HTML to the WebBrowser control
            // otherwise the "Back" function doesn't work.

            string shortcut_contents, shortcut_url, shortcut_name;


            // Define the string holding the HTML document.
            // We use StringBuilder because we're going to be appending
            // a lot of strings togther, and this is what StringBuilder
            // is good at! Using the string type alone would be a lot
            // slower and less memory-efficient.

            StringBuilder htmldoc = new StringBuilder();

            htmldoc.Append("<html>");
            htmldoc.Append("<title>Windows_Mobile_Web_Browser2</title>");
            htmldoc.Append("<body bgcolor=\"#DDEEFF\">");

            htmldoc.Append("<h2>Favorite Websites</h2><hr>");

            // Add some pre-existing websites. A good place to add your own favorites!

            htmldoc.Append("<ul>");
            htmldoc.Append("<li><a href = \"Http://mobile.msn.com\">MSN Mobile</a></li>");
            htmldoc.Append("<li><a href = \"Http://pocketpcthoughts.com\">Pocket PC Thoughts</a></li>");
            htmldoc.Append("<li><a href = \"Http://www.mappoint.com\">Map Point</a></li>");
            htmldoc.Append("</ul>");

            // Iterate through user's favorites and add these to the page.

            // Obtain the location of the shortcuts directory.
            string myfavs = "\\windows\\" + System.Environment.SpecialFolder.Favorites.ToString();

            // Obtain a list of all the shortcuts.
            string[] shortcut_files = Directory.GetFiles(myfavs);

            // Start building a list in the HTML document.
            htmldoc.Append("<ul>");

            // Obtain the name tha URL for each shortcut and add to HTML doc.
            foreach (string shortcut_filename in shortcut_files)
            {
                FileStream myFS = File.Open(shortcut_filename, FileMode.Open);
                StreamReader reader = new StreamReader(myFS);
                shortcut_contents = reader.ReadToEnd();

                // Extract the URL from the shortcut.
                shortcut_url = shortcut_contents.Substring(24);

                // Extract the name of the link from the shortcut.
                shortcut_name = shortcut_filename.Substring(19);
                shortcut_name = shortcut_name.Remove(shortcut_name.Length - 4, 4);

                htmldoc.Append("<li><a href = \"");
                htmldoc.Append(shortcut_url);
                htmldoc.Append("\">");
                htmldoc.Append(shortcut_name);
                htmldoc.Append("</a></li>");
                reader.Close();
            }

            htmldoc.Append("</ul>");
            htmldoc.Append("</body></html>");

            // Save the file as an HTH webpage.
            StreamWriter sw = new StreamWriter("browser_index.htm");
            sw.Write(htmldoc);
            sw.Flush();
            sw.Close();

        }



        // Menu Related Methods

        private void UpdateLeftSoftKey(TabPage current_tab)
        {
            // Update the left softkey, which is used for Back,
            // as if the webpage displayed is the Home page, there is
            // nowhere to go "Back" to.

            if (current_tab.Text == "Home") // hmmm..
                menuItem_left.Enabled = false;
            else
                menuItem_left.Enabled = true;
        }

        private void menuItem_right_Popup(object sender, EventArgs e)
        {
            // Alter the right-hand menu's options. This method is called 
            // immediately before the menu opens, allowing the options 
            // available to be changed.

            // Disable "close tab" menu if there is only one browser tab
            if (listOfTabpages.Count == 1)
                menuItem_right.MenuItems[menuItem_right.MenuItems.IndexOf(menuItem_CloseCurrentTab)].Enabled = false;
            else
                menuItem_right.MenuItems[menuItem_right.MenuItems.IndexOf(menuItem_CloseCurrentTab)].Enabled = true;

            // Disable "open tab" if there are too many already open.
            if (listOfTabpages.Count == 10)
                menuItem_right.MenuItems[menuItem_right.MenuItems.IndexOf(menuItem_OpenANewTab)].Enabled = false;
            else
                menuItem_right.MenuItems[menuItem_right.MenuItems.IndexOf(menuItem_OpenANewTab)].Enabled = true;


        }

        private void menuItem_OpenANewTab_Click(object sender, EventArgs e)
        {
            // Open a new tab, and display default webpage.

            CreateANewTab();
            WebBrowser thiswebpage = GetCurrentWebBrowser();
            thiswebpage.Navigate(new Uri("file://\\browser_index.htm"));
        }

        private void menuItem_CloseCurrentTab_Click(object sender, EventArgs e)
        {

            // Close the current tab.

            // Switch off the handler for the "change selected tab" message.
            // We'll be changing the selected tab as we close the current one,
            // and don't need any code to be triggered at this time.
            handlerActive = false;


            // Keep track of the index of the currently select tab.
            int selected_tab_index = tabControl.SelectedIndex;


            // Delete the web browser on the current tab page.
            TabPage current_tab = tabControl.TabPages[selected_tab_index];

            WebBrowser current_wb = GetWebBrowser(current_tab);
            current_wb.Dispose();					    // Delete the web control.

            // Remove the tab and browser from the internal lists
            listOfTabpages.Remove(current_tab);	    // Delete from list.	
            listOfWebpages.Remove(current_wb);	    // Delete from list.



            // Remove the tab from the tab control
            tabControl.TabPages.RemoveAt(selected_tab_index);

            // Following IE7's example, we try to select a page to the right first,
            // and if not exists, select a page to the left.

            if (selected_tab_index > (listOfTabpages.Count - 1))
                tabControl.SelectedIndex = selected_tab_index - 1;
            else
                tabControl.SelectedIndex = selected_tab_index;

            tabControl.Refresh();

            HideAllWebBrowsers();
            ShowCurrentWebBrowser();

            // Switch on the code that handles the change selected tab message
            handlerActive = true;

        }

        private void menuItem_EnterAUrl_Click(object sender, EventArgs e)
        {
            // Allow the user to enter a new URL.
            // Depending on the values returned, the new URL will be opened
            // in the existing Web Windows_Mobile_Web_Browser2 control, or in a new one.


            EnterAUrlLForm myEnterAUrlForm = new EnterAUrlLForm();
            myEnterAUrlForm.ShowDialog();

            if (newUrl != null)
            {
                Uri url = null;

                try
                {
                    url = new Uri(newUrl);
                }
                catch (Exception invalid_url)
                {
                    MessageBox.Show("Error: Cannot open the website " + invalid_url.ToString());
                }

                if (openInNewTab == true)
                    CreateANewTab();

                WebBrowser thiswebpage = GetCurrentWebBrowser();
                thiswebpage.Navigate(url);

            }

        }

        private void menuItem_left_Click(object sender, EventArgs e)
        {
            // The Go Back menu option. 
            // This will go back a page, if that is possible.
            WebBrowser thiswebpage = GetCurrentWebBrowser();
            if (thiswebpage.CanGoBack) thiswebpage.GoBack();
        }
    }
}